package eu.integration;

import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.Map;

import eu.common.config.ConfigEngine;
import eu.common.config.ConfigException;
import eu.common.toolkits.ResourceUtil;

/**
 * 组件集成网
 * 
 * @author WZZ
 * 
 */
public class IntegrationNet {

	/**
	 * 名字到netid的映射
	 */
	private Map<String, Integer> idMap = new HashMap<String, Integer>();

	/**
	 * 网络节点
	 */
	private Map<Integer, NetNode> nodes = new HashMap<Integer, NetNode>();

	/**
	 * 信息流向
	 */
	private Map<PackageOrigin, Integer> streams = new HashMap<PackageOrigin, Integer>();

	/**
	 * 向网络发送包
	 * 
	 * @param pack
	 */
	public int send(Package pack, ModuleFace sender) {
		pack.setFrom(sender.getNetId());
		PackageOrigin origin = new PackageOrigin(pack.getFrom(),
				pack.getSignal());
		if (!streams.containsKey(origin))
			return SEND_RESULT.NO_STREAM;
		int des = streams.get(origin);
		if (!nodes.containsKey(des))
			return SEND_RESULT.INTERNAL_ERROR;
		NetNode node = nodes.get(des);
		node.send(pack);
		return SEND_RESULT.OK;
	}

	public static class SEND_RESULT {

		public static final int OK = 0;

		public static final int NO_STREAM = 1;

		public static final int INTERNAL_ERROR = 2;
	}

	/**
	 * 从配置文件初始化
	 * 
	 * @throws ConfigException
	 */
	public void initFromConf() throws ConfigException {
		ConfigEngine engine = ConfigEngine.getEngine(
				ConfigEngine.EngineType.XMLEngine,
				ResourceUtil.getResourcePath("intergration.xml"), "UTF-8");
		engine.locate("/net/modules");
		// load module
		for (String id : engine.getValues("module/id")) {
			ModuleFace module = loadModule(engine.getValue("module[id='" + id
					+ "']/class"));
			if (null != module) {
				module.setNetId(idMap.size());
				idMap.put(id, module.getNetId());
				nodes.put(module.getNetId(), module);
			}
		}
		engine.locate("/net/groups");
		// load groups
		for (String id : engine.getValues("group/id")) {
			ModuleGroup group = new ModuleGroup();
			group.setNetId(idMap.size());
			for (String mid : engine.getValues("group[id='" + id
					+ "']/module/id")) {
				NetNode face = nodes.get(idMap.get(mid));
				group.addModule(face);
			}
			idMap.put(id, group.getNetId());
			nodes.put(group.getNetId(), group);
		}
		// load links
		engine.locate("/net/streams");
		for (String id : engine.getValues("stream/id")) {
			String base = "stream[id='"+id+"']/";
			if (!idMap.containsKey(engine.getValue(base + "from"))
					|| !idMap.containsKey(engine.getValue(base + "/to"))) {
				continue;
			}
			streams.put(
					new PackageOrigin(
							idMap.get(engine.getValue(base + "/from")), Integer
									.parseInt(engine.getValue(base + "/signal"))),
					idMap.get(engine.getValue(base + "/to")));
		}

		// notify
		for (NetNode node : nodes.values()) {
			node.notifyNetStart(this);
		}
	}

	public static void main(String[] args) throws ConfigException {
		IntegrationNet net = new IntegrationNet();
		net.initFromConf();
	}

	/**
	 * 加载类
	 * 
	 * @param clazz
	 * @return
	 */
	private ModuleFace loadModule(String clazz) {
		ClassLoader loader = new URLClassLoader(scanLib());
		Object obj = null;
		try {
			obj = loader.loadClass(clazz).newInstance();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}

		if (obj instanceof ModuleFace)
			return (ModuleFace) obj;
		return null;
	}

	public ModuleFace getModule(String id) {
		NetNode node = nodes.get(idMap.get(id));
		if (null == node || !(node instanceof ModuleFace))
			return null;
		return (ModuleFace) node;
	}

	private URL[] scanLib() {
		return new URL[] {};
	}
}
